﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Windows.Forms;
using System.ComponentModel.Design;
using System.Reflection;
using System.Diagnostics;
using System.Xml;

namespace ProgNetComponents.MDI
{
    /// <summary>
    /// Helper class for MDI documents
    /// </summary>
    public class MdiHelper : Component
    {
        /// <summary>
        /// Gets the instance.
        /// </summary>
        /// <value>
        /// The instance.
        /// </value>
        public static MdiHelper Instance
        {
            get;
            private set;
        }
        #region Members
        /// <summary>
        /// SeparateString
        /// </summary>
        private const string SeparateString = "#\f#";
        /// <summary>
        /// _MdiParent
        /// </summary>
        private Form _MdiParent;
        /// <summary>
        /// AllChildren
        /// </summary>
        private Dictionary<string, List<MdiChildClass>> AllChildren = new Dictionary<string, List<MdiChildClass>>();
        #endregion

        #region Events
        /// <summary>
        /// Occurs when [compare parameters].
        /// </summary>
        public event EventHandler<CompareArgsEventArgs> CompareParameters;
        /// <summary>
        /// Occurs when [create parameter].
        /// </summary>
        public event EventHandler<CreateParameterEventArgs> CreateParameter;
        /// <summary>
        /// Occurs when [parameter to string].
        /// </summary>
        public event EventHandler<ParameterToStringEventArgs> ParameterToString;
        /// <summary>
        /// Occurs when [form created].
        /// </summary>
        public event FormCreateEventHandler FormCreated;

        #endregion

        #region Properties
        /// <summary>
        /// Gets or sets the MDI parent.
        /// </summary>
        /// <value>
        /// The MDI parent.
        /// </value>
        [RefreshProperties(RefreshProperties.All)]
        public Form MdiParent
        {
            get { return _MdiParent; }
            set
            {
                if (_MdiParent != null)
                {
                    _MdiParent.ResizeBegin -= new EventHandler(_MdiParent_ResizeBegin);
                    _MdiParent.ResizeEnd -= new EventHandler(_MdiParent_ResizeEnd);
                }
                _MdiParent = value;
                if (_MdiParent != null)
                {
                    _MdiParent.ResizeBegin += new EventHandler(_MdiParent_ResizeBegin);
                    _MdiParent.ResizeEnd += new EventHandler(_MdiParent_ResizeEnd);
                }
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether [maximize forms].
        /// </summary>
        /// <value>
        ///   <c>true</c> if [maximize forms]; otherwise, <c>false</c>.
        /// </value>
        public bool MaximizeForms
        {
            get;
            set;
        }

        /// <summary>
        /// Gets or sets a value indicating whether [log exceptions].
        /// </summary>
        /// <value>
        ///   <c>true</c> if [log exceptions]; otherwise, <c>false</c>.
        /// </value>
        public bool LogExceptions
        {
            get;
            set;
        }
        /// <summary>
        /// Gets or sets a value indicating whether [log inner exceptions].
        /// </summary>
        /// <value>
        ///   <c>true</c> if [log inner exceptions]; otherwise, <c>false</c>.
        /// </value>
        public bool LogInnerExceptions
        {
            get;
            set;
        }

        /// <summary>
        /// Handles the ResizeEnd event of the _MdiParent control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
        void _MdiParent_ResizeEnd(object sender, EventArgs e)
        {
            Form[] forms = (sender as Form).MdiChildren;
            if (forms != null)
            {
                foreach (Form f in forms)
                {
                    f.ResumeLayout(true);
                }
            }
        }

        /// <summary>
        /// Handles the ResizeBegin event of the _MdiParent control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
        void _MdiParent_ResizeBegin(object sender, EventArgs e)
        {
            Form[] forms = (sender as Form).MdiChildren;
            if (forms != null)
            {
                foreach (Form f in forms)
                {
                    f.SuspendLayout();
                }
            }
        }


        #endregion

        #region CTOR
        /// <summary>
        /// Initializes a new instance of the <see cref="MdiHelper"/> class.
        /// </summary>
        public MdiHelper()
        {
            LogExceptions = true;
            LogInnerExceptions = true;
            Instance = this;
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="MdiHelper"/> class.
        /// </summary>
        /// <param name="container">The container.</param>
        /// <exception cref="System.Exception">Only one MdiHelper can be added.</exception>
        public MdiHelper(IContainer container)
        {
            Instance = this;
            if (container != null)
            {
                foreach (object o in container.Components)
                {
                    if (o is MdiHelper)
                        throw new Exception("Only one MdiHelper can be added.");
                }
                container.Add(this);
                IDesignerEventService service = this.GetService(typeof(IDesignerEventService)) as IDesignerEventService;
                if (service != null)
                {
                    if (service.ActiveDesigner != null && service.ActiveDesigner.RootComponent !=null &&
                        service.ActiveDesigner.RootComponent is Form)
                    {
                        MdiParent = service.ActiveDesigner.RootComponent as Form;
                    }
                }
            }
            LogExceptions = true;
            LogInnerExceptions = true;
        }
        #endregion

        #region Public Methods
        /// <summary>
        /// Adds the fake opened form string.
        /// </summary>
        /// <param name="formType">Type of the form.</param>
        /// <param name="shown">if set to <c>true</c> [shown].</param>
        /// <param name="currentString">The current string.</param>
        /// <param name="args">The arguments.</param>
        /// <returns></returns>
        public string AddFakeOpenedFormString(Type formType, bool shown, string currentString, params object[] args)
        {
            currentString = currentString.AppendString(SeparateString);
            string paramStr= "";
            if (args != null)
            {
                foreach (object o in args)
                {
                    paramStr = paramStr.AppendString("\f");
                    paramStr += ParamToString(o);
                }
            }
            currentString += formType.FullName + ";" + shown + ";" + paramStr;
            return currentString;
        }

        /// <summary>
        /// Gets the opened forms string.
        /// </summary>
        /// <returns></returns>
        public string GetOpenedFormsString()
        {
            string str = "";
            List<string> list = GetOpenedFormsStringList();
            foreach (string s in list)
            {
                str = str.AppendString(SeparateString);
                str += s;
            }
            return str;
        }

        /// <summary>
        /// Opens the forms from string.
        /// </summary>
        /// <param name="str">The string.</param>
        public void OpenFormsFromString(string str)
        {
            List<string> list = (str + SeparateString).GetMatches("(.*?)" + SeparateString);
            OpenFormsFromStringList(list);
        }

        /// <summary>
        /// Opens the forms from string list.
        /// </summary>
        /// <param name="list">The list.</param>
        public void OpenFormsFromStringList(List<string> list)
        {
            Type type = null;
            bool show = false;
            List<Dictionary<int, string>> lista = null;
            List<object> paramsList = null;
            string[] parts = null;
            Type paramType;
            bool isOk = true;
            foreach (string s in list)
            {
                paramsList = null;
                show = false;
                isOk = true;
                lista = s.GetMatches("([^;]*);([^;]*);(.*)", new int[] { 1, 2, 3 });
                if (lista.Count == 1)
                {
                    if (lista[0].Count == 3)
                    {
                        try
                        {
                            type = this.GetType(lista[0][1]);
                            
                            if (type == null)
                                continue;
                            bool.TryParse(lista[0][2], out show);
                            if (lista[0][3].IsNotNull())
                            {
                                parts = lista[0][3].Split('\f');
                                foreach (string part in parts)
                                {
                                    if (paramsList == null)
                                        paramsList = new List<object>();
                                   
                                    paramType = this.GetType(part.GetFirstMatch("([^;]*);.*"));
                                    paramsList.Add(OnCreateParameter(paramType, part.GetFirstMatch(".*;(.*)")));
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            if (LogExceptions)
                                ex.LogError();
                            isOk = false;
                            continue;
                        }
                        if (isOk)
                        {
                            object[] paramsTab = null;
                            if(paramsList!=null)
                                paramsTab = paramsList.ToArray();
                            MdiOptions opt = new MdiOptions(true, true, show, show);
                            GetMdiChildFull(type, opt, paramsTab);
                        }
                    }
                }
            }
        }

        /// <summary>
        /// Gets the active child string.
        /// </summary>
        /// <returns></returns>
        public string GetActiveChildString()
        {
            string type = "";
            string shown = "";
            string paramStr = "";
           
            foreach (KeyValuePair<string, List<MdiChildClass>> kvp in AllChildren)
            {
                type = kvp.Key;
                foreach (MdiChildClass mdi in kvp.Value)
                {
                    if (mdi.Form == this.MdiParent.ActiveMdiChild)
                    {
                        shown = (mdi.Form.Visible || IsOpened(mdi.Form)).ToString();
                        paramStr = "";
                        if (mdi.Parameters != null)
                        {
                            foreach (object o in mdi.Parameters)
                            {
                                if (o != null)
                                {
                                    paramStr = paramStr.AppendString("\f");
                                    paramStr += o.GetType().FullName + ";" + o.ToString();
                                }
                            }
                        }
                        return type + ";" + shown + ";" + paramStr;
                    }
                }
            }
            return "";
        }
        /// <summary>
        /// Determines whether the specified form is opened.
        /// </summary>
        /// <param name="form">The form.</param>
        /// <returns></returns>
        private bool IsOpened(Form form)
        {
            foreach (Form f in Application.OpenForms)
                if (f == form)
                    return true;
            return false;
        }
        /// <summary>
        /// Gets the opened forms string list.
        /// </summary>
        /// <returns></returns>
        public List<string> GetOpenedFormsStringList()
        {
            List<string> list = new List<string>();
            string type = "";
            string shown = "";
            string paramStr = "";
            foreach (KeyValuePair<string, List<MdiChildClass>> kvp in AllChildren)
            {
                type = kvp.Key;
                foreach (MdiChildClass mdi in kvp.Value)
                {
                    shown = (mdi.Form.Visible || IsOpened(mdi.Form)).ToString();
                    paramStr = "";
                    if (mdi.Parameters != null)
                    {
                        foreach (object o in mdi.Parameters)
                        {
                            paramStr = paramStr.AppendString("\f");
                            paramStr += ParamToString(o);
                        }
                    }
                    list.Add(type + ";" + shown + ";" + paramStr);
                }
            }
            return list;
        }

        /// <summary>
        /// Gets the MDI child full.
        /// </summary>
        /// <param name="childType">Type of the child.</param>
        /// <param name="options">The options.</param>
        /// <param name="args">The arguments.</param>
        /// <returns></returns>
        public Form GetMdiChildFull(Type childType, MdiOptions options, params object[] args )
        {
            Form f = null;
            if (MdiParent != null && MdiParent.IsMdiContainer && childType != null)
            {
                List<MdiChildClass> children = null;
                if (AllChildren.ContainsKey(childType.FullName))
                    children = AllChildren[childType.FullName];
                else
                {
                    children = new List<MdiChildClass>();
                    AllChildren.Add(childType.FullName, children);
                }
                bool wasCreated = false;
                CompareArgsEventArgs e = null;
                foreach (MdiChildClass mdi in children)
                {
                    e = new CompareArgsEventArgs(args, mdi.Parameters, childType);
                    e.TheSame = CompareArgs(args, mdi.Parameters);
                    if (CompareParameters != null)
                    {
                        CompareParameters(this, e);
                    }
                    if (e.TheSame)
                    {
                        f = mdi.Form;
                        break;
                    }
                }
                if (f == null && options.Create)
                {
                    wasCreated = true;
                    f = CreateForm(childType, args);
                    if (f != null)
                    {
                        f.MdiParent = MdiParent;
                        if (options.Remember)
                        {
                            MdiChildClass mdi = new MdiChildClass();
                            if (args != null && args.Length == 0)
                                args = null;
                            mdi.Parameters = args;
                            mdi.Form = f;
                            children.Add(mdi);
                        }
                    }
                }
                if ((!wasCreated && (f.Visible || options.ShowIfHidden)) || (wasCreated && options.ShowIfCreate))
                {
                    if (f != null)
                    {
                        if (MaximizeForms)
                            f.WindowState = FormWindowState.Maximized;
                        f.Show();
                        f.BringToFront();
                    }
                }
            }
            
            return f;
        }
        /// <summary>
        /// Gets the MDI child full.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="options">The options.</param>
        /// <param name="args">The arguments.</param>
        /// <returns></returns>
        public T GetMdiChildFull<T>(MdiOptions options, params object[] args) where T : Form
        {
            return (T)GetMdiChildFull(typeof(T), options, args);
        }

        /// <summary>
        /// Gets the MDI child.
        /// </summary>
        /// <param name="childType">Type of the child.</param>
        /// <param name="args">The arguments.</param>
        /// <returns></returns>
        public Form GetMdiChild(Type childType, params object[] args)
        {
            return GetMdiChildFull(childType, MdiOptions.DefaultNoShowHidden, args);
        }

        /// <summary>
        /// Gets the MDI child.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="args">The arguments.</param>
        /// <returns></returns>
        public T GetMdiChild<T>(params object[] args) where T : Form
        {
            return (T)GetMdiChild(typeof(T), args);
        }

        /// <summary>
        /// Tries the add child.
        /// </summary>
        /// <param name="f">The f.</param>
        /// <param name="args">The arguments.</param>
        /// <returns></returns>
        public bool TryAddChild(Form f, params object[] args)
        {
            bool added = false;
            if (f != null)
            {
                Type childType = f.GetType();
                if (MdiParent != null && MdiParent.IsMdiContainer && childType != null)
                {
                    List<MdiChildClass> children = null;
                    if (AllChildren.ContainsKey(childType.FullName))
                        children = AllChildren[childType.FullName];
                    else
                    {
                        children = new List<MdiChildClass>();
                        AllChildren.Add(childType.FullName, children);
                    }

                    CompareArgsEventArgs e = null;
                    foreach (MdiChildClass mdi in children)
                    {
                        e = new CompareArgsEventArgs(args, mdi.Parameters, childType);
                        e.TheSame = CompareArgs(args, mdi.Parameters);
                        if (CompareParameters != null)
                        {
                            CompareParameters(this, e);
                        }
                        if (e.TheSame)
                        {
                            return false;
                        }
                    }
                    MdiChildClass m = new MdiChildClass();
                    m.Form = f;
                    m.Parameters = args;
                    children.Add(m);
                    added = true;
                    f.FormClosed -= new FormClosedEventHandler(f_FormClosed);
                    f.FormClosed += new FormClosedEventHandler(f_FormClosed);
                }
            }
            return added;
        }

        /// <summary>
        /// Removes the child.
        /// </summary>
        /// <param name="f">The f.</param>
        /// <returns></returns>
        public bool RemoveChild(Form f)
        {
            if (f != null)
            {
                if (AllChildren.ContainsKey(f.GetType().FullName))
                {
                    MdiChildClass mdiCC = null;
                    List<MdiChildClass> list = AllChildren[f.GetType().FullName];
                    foreach (MdiChildClass c in list)
                    {
                        if (c.Form == f)
                        {
                            mdiCC = c;
                            break;
                        }
                    }
                    if (mdiCC != null)
                    {
                        list.Remove(mdiCC);
                        return true;
                    }
                }
            }
            return false;
        }

        /// <summary>
        /// Adds the or update child.
        /// </summary>
        /// <param name="f">The f.</param>
        /// <param name="args">The arguments.</param>
        /// <returns></returns>
        public bool AddOrUpdateChild(Form f, params object[] args)
        {
            RemoveChild(f);
            return TryAddChild(f, args);
        }
        #endregion

        #region private methods

        /// <summary>
        /// Called when [create parameter].
        /// </summary>
        /// <param name="paramType">Type of the parameter.</param>
        /// <param name="value">The value.</param>
        /// <returns></returns>
        private object OnCreateParameter(Type paramType, string value)
        {
            object o = null;
            try
            {
                o = Convert.ChangeType(value, paramType);
            }
            catch (Exception ex)
            {
                if (LogExceptions)
                    ex.LogError();
            }
            if (CreateParameter != null)
            {
                CreateParameterEventArgs e = new CreateParameterEventArgs(value, paramType);
                CreateParameter(this, e);
                o = e.Parameter;
            }
            return o;
        }
        /// <summary>
        /// Parameters to string.
        /// </summary>
        /// <param name="parameter">The parameter.</param>
        /// <returns></returns>
        private string ParamToString(object parameter)
        {
            if (parameter != null)
            {
                string str = parameter.GetType().FullName + ";";
                string val = "";
                if (ParameterToString != null)
                {
                    ParameterToStringEventArgs e = new ParameterToStringEventArgs(parameter);
                    ParameterToString(this, e);
                    val = e.StringValue;
                    str += val;
                }
                if (val.IsNull())
                {
                    str += parameter.ToString();
                }
                return str;
            }
            return string.Empty;
        }
        /// <summary>
        /// Compares the arguments.
        /// </summary>
        /// <param name="args1">The args1.</param>
        /// <param name="args2">The args2.</param>
        /// <returns></returns>
        private bool CompareArgs( object[] args1, object[] args2)
        {
            if (args1 == null && args2 == null)
                return true;
            if (args1 == null && args2.Length == 0)
                return true;
            if (args2 == null && args1.Length == 0)
                return true;
            if (args1 == null || args2 == null)
                return false;
            if (args1.Length != args2.Length)
                return false;
            for (int i = 0; i < args1.Length; i++)
            {
                if (args1[i] == null && args2[i] == null)
                    continue;
                if (args1[i] == null)
                    return false;
                if (!args1[i].Equals(args2[i]))
                    return false;
            }
            return true;
        }

        /// <summary>
        /// Creates the form.
        /// </summary>
        /// <param name="childType">Type of the child.</param>
        /// <param name="args">The arguments.</param>
        /// <returns></returns>
        private Form CreateForm(Type childType, params object[] args)
        {
            Form f = null;
            try
            {
                f = Activator.CreateInstance(childType, args) as Form;
                if (f != null)
                {
                    f.FormClosed += new FormClosedEventHandler(f_FormClosed);
                    if(FormCreated!=null)
                        FormCreated(this, new FormCreateEventArgs(f));
                }
            }
            catch (Exception ex)
            {
                if (LogExceptions)
                    ex.LogError();
            }
            return f;
        }

        /// <summary>
        /// Handles the FormClosed event of the f control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="FormClosedEventArgs"/> instance containing the event data.</param>
        private void f_FormClosed(object sender, FormClosedEventArgs e)
        {
            Form f = sender as Form;
            if (AllChildren.ContainsKey(f.GetType().FullName))
            {
                List<MdiChildClass> list = AllChildren[f.GetType().FullName];
                MdiChildClass m = null;
                if (list != null)
                {
                    foreach (MdiChildClass mdi in list)
                    {
                        if (mdi.Form == f)
                        {
                            m = mdi;
                            break;
                        }
                    }
                    if (m != null)
                        list.Remove(m);
                }
            }
        }

        #endregion

        /// <summary>
        /// 
        /// </summary>
        private class MdiChildClass
        {
            /// <summary>
            /// Gets or sets the parameters.
            /// </summary>
            /// <value>
            /// The parameters.
            /// </value>
            public object[] Parameters
            {
                get;
                set;
            }
            /// <summary>
            /// Gets or sets the form.
            /// </summary>
            /// <value>
            /// The form.
            /// </value>
            public Form Form
            {
                get;
                set;
            }
        }

        private List<Form> Forms = new List<Form>();

        public void MoveForm(Form form, int index)
        {
            Forms.MoveItem(form, index);
        }

        
        public string GetFormString(Type formType, params object[] args)
        {
            XmlDocument d = new XmlDocument();
            var main = d.AppendChildElement("Form");
            main.AppendAttribute("Type", formType);
            if (args != null)
            {
                int idx = 0;
                foreach (var a in args)
                {
                    if (a != null)
                        main.AppendChildElement("Parameter" + (idx++).ToString(), ConvertParameterToString(a));
                    else
                        main.AppendChildElement("Parameter" + (idx++).ToString(), string.Empty).AppendAttribute("IsNull", true);
                }
            }
            //main.AppendAttribute("att", 1);
            return d.ToFormatedString();
        }

        public string ConvertParameterToString(object parameter)
        {
            var converter = TypeDescriptor.GetConverter(parameter);
            if (converter != null && converter.CanConvertTo(typeof(string)))
                return (string)converter.ConvertTo(parameter, typeof(string));
            return parameter.ToString();
        }
    }

    [Flags]
    public enum MdiFormOptions
    {
        Create = 1,
        ShowIfHidden = 2,
        ShowIfCreate = 4,
        Remember = 8
    }

    /// <summary>
    /// Mdi Options
    /// </summary>
    public struct MdiOptions
    {
        /// <summary>
        /// Initializes the <see cref="MdiOptions"/> struct.
        /// </summary>
        static MdiOptions()
        {

        }

        /// <summary>
        /// _Remember
        /// </summary>
        private bool _Remember;
        /// <summary>
        /// _Create
        /// </summary>
        private bool _Create;
        /// <summary>
        /// _ShowIfCreate
        /// </summary>
        private bool _ShowIfCreate;
        /// <summary>
        /// _ShowIfHidden
        /// </summary>
        private bool _ShowIfHidden;

        /// <summary>
        /// Initializes a new instance of the <see cref="MdiOptions"/> struct.
        /// </summary>
        /// <param name="remember">if set to <c>true</c> [remember].</param>
        /// <param name="create">if set to <c>true</c> [create].</param>
        /// <param name="showIfCreate">if set to <c>true</c> [show if create].</param>
        /// <param name="showIfHidden">if set to <c>true</c> [show if hidden].</param>
        public MdiOptions(bool remember, bool create, bool showIfCreate, bool showIfHidden)
        {
            _Remember = remember;
            _Create = create;
            _ShowIfCreate = showIfCreate;
            _ShowIfHidden = showIfHidden;
        }

        /// <summary>
        /// Remember, Create, ShowIfCreate, ShowIfHidden
        /// </summary>
        public static readonly MdiOptions Default = new MdiOptions(true, true, true, true);
        /// <summary>
        /// Create, ShowIfCreate, ShowIfHidden
        /// </summary>
        public static readonly MdiOptions DefaultNoRemember = new MdiOptions(false, true, true, true);
        /// <summary>
        /// ShowIfHidden
        /// </summary>
        public static readonly MdiOptions DefaultNoCreate = new MdiOptions(false, false, false, true);
        /// <summary>
        /// Create, ShowIfHidden
        /// </summary>
        public static readonly MdiOptions DefaultNoShowCreate = new MdiOptions(false, true, false, true);
        /// <summary>
        /// Remember, Create
        /// </summary>
        public static readonly MdiOptions DefaultNoShow = new MdiOptions(true, true, false, false);
        /// <summary>
        /// Remember, Create, ShowIfCreate
        /// </summary>
        public static readonly MdiOptions DefaultNoShowHidden = new MdiOptions(true, true, true, false);

        /// <summary>
        /// Gets or sets a value indicating whether [remember].
        /// </summary>
        /// <value>
        ///   <c>true</c> if [remember]; otherwise, <c>false</c>.
        /// </value>
        public bool Remember
        {
            get { return _Remember; }
            set { _Remember = value; }
        }
        /// <summary>
        /// Gets or sets a value indicating whether [create].
        /// </summary>
        /// <value>
        ///   <c>true</c> if [create]; otherwise, <c>false</c>.
        /// </value>
        public bool Create
        {
            get { return _Create; }
            set { _Create = value; }
        }
        /// <summary>
        /// Gets or sets a value indicating whether [show if create].
        /// </summary>
        /// <value>
        ///   <c>true</c> if [show if create]; otherwise, <c>false</c>.
        /// </value>
        public bool ShowIfCreate
        {
            get { return _ShowIfCreate; }
            set { _ShowIfCreate = value; }
        }
        /// <summary>
        /// Gets or sets a value indicating whether [show if hidden].
        /// </summary>
        /// <value>
        ///   <c>true</c> if [show if hidden]; otherwise, <c>false</c>.
        /// </value>
        public bool ShowIfHidden
        {
            get { return _ShowIfHidden; }
            set { _ShowIfHidden = value; }
        }
    }

    /// <summary>
    /// CompareArgsEventArgs
    /// </summary>
    public class CompareArgsEventArgs : EventArgs
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="CompareArgsEventArgs"/> class.
        /// </summary>
        /// <param name="params1">The params1.</param>
        /// <param name="params2">The params2.</param>
        /// <param name="childType">Type of the child.</param>
        public CompareArgsEventArgs(object[] params1, object[] params2, Type childType)
        {
            this._ChildType = childType;
            this._Params1 = params1;
            this._Params2 = params2;
        }

        /// <summary>
        /// _Params1
        /// </summary>
        private object[] _Params1;
        /// <summary>
        /// _Params2
        /// </summary>
        private object[] _Params2;
        /// <summary>
        /// _ChildType
        /// </summary>
        private Type _ChildType;

        /// <summary>
        /// Gets the params1.
        /// </summary>
        /// <value>
        /// The params1.
        /// </value>
        public object[] Params1
        {
            get
            {
                return _Params1;
            }
        }
        /// <summary>
        /// Gets the params2.
        /// </summary>
        /// <value>
        /// The params2.
        /// </value>
        public object[] Params2
        {
            get
            {
                return _Params2;
            }
        }
        /// <summary>
        /// Gets the type of the child.
        /// </summary>
        /// <value>
        /// The type of the child.
        /// </value>
        public Type ChildType
        {
            get { return _ChildType; }
        }
        /// <summary>
        /// Gets or sets a value indicating whether [the same].
        /// </summary>
        /// <value>
        ///   <c>true</c> if [the same]; otherwise, <c>false</c>.
        /// </value>
        public bool TheSame
        {
            get;
            set;
        }

    }

    /// <summary>
    /// CreateParameterEventArgs
    /// </summary>
    public class CreateParameterEventArgs : EventArgs
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="CreateParameterEventArgs"/> class.
        /// </summary>
        /// <param name="stringValue">The string value.</param>
        /// <param name="paramType">Type of the parameter.</param>
        public CreateParameterEventArgs(string stringValue, Type paramType)
        {
            this._StringValue = stringValue;
            this._ParamType = paramType;
        }

        /// <summary>
        /// _StringValue
        /// </summary>
        private string _StringValue;
        /// <summary>
        /// Gets the string value.
        /// </summary>
        /// <value>
        /// The string value.
        /// </value>
        public string StringValue
        {
            get
            {
                return _StringValue;
            }
        }

        /// <summary>
        /// _ParamType
        /// </summary>
        private Type _ParamType;
        /// <summary>
        /// Gets the type of the parameter.
        /// </summary>
        /// <value>
        /// The type of the parameter.
        /// </value>
        public Type ParamType
        {
            get { return _ParamType; }
        }
        /// <summary>
        /// Gets or sets the parameter.
        /// </summary>
        /// <value>
        /// The parameter.
        /// </value>
        public object Parameter
        {
            get;
            set;
        }
    }

    /// <summary>
    /// ParameterToStringEventArgs
    /// </summary>
    public class ParameterToStringEventArgs : EventArgs
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="ParameterToStringEventArgs"/> class.
        /// </summary>
        /// <param name="Parameter">The parameter.</param>
        public ParameterToStringEventArgs(object Parameter)
        {
            this._Parameter = Parameter;
        }

        /// <summary>
        /// _Parameter
        /// </summary>
        private object _Parameter;
        /// <summary>
        /// Gets or sets the string value.
        /// </summary>
        /// <value>
        /// The string value.
        /// </value>
        public string StringValue
        {
            get;
            set;
        }

        /// <summary>
        /// Gets the parameter.
        /// </summary>
        /// <value>
        /// The parameter.
        /// </value>
        public object Parameter
        {
            get { return _Parameter; }
        }

    }
    /// <summary>
    /// FormCreateEventHandler
    /// </summary>
    /// <param name="sender">The sender.</param>
    /// <param name="e">The <see cref="FormCreateEventArgs"/> instance containing the event data.</param>
    public delegate void FormCreateEventHandler (object sender, FormCreateEventArgs e);

    /// <summary>
    /// FormCreateEventArgs
    /// </summary>
    public class FormCreateEventArgs : EventArgs
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="FormCreateEventArgs"/> class.
        /// </summary>
        /// <param name="f">The f.</param>
        public FormCreateEventArgs(Form f)
        {
            Form = f;
        }

        /// <summary>
        /// Gets the form.
        /// </summary>
        /// <value>
        /// The form.
        /// </value>
        public Form Form
        {
            get;
            private set;
        }
    }
}
